﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using MinimalistFoodStreet.BackEnd.Infrastructure.Attributes;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Request.Functions;
using MinimalistFoodStreet.BackEnd.Infrastructure.Dtos.Response;
using MinimalistFoodStreet.BackEnd.Infrastructure.EFCore;
using MinimalistFoodStreet.BackEnd.Infrastructure.Tools;
using MinimalistFoodStreet.BackEnd.Server.IServer.Tables;
using MinimalistFoodStreet.BackEnd.Server.Server.RequestExtend.Functions;
using MinimalistFoodStreet.BackEnd.Server.Server.ResponseIqExtend;

namespace MinimalistFoodStreet.BackEnd.Server.Server.Tables
{
    [InjectClass]
    public class CommentsServer : ICommentsServer
    {
        private readonly ServerRepository _serverRepository;
        private readonly IConfiguration _configuration;

        public CommentsServer(DbContext dbContext, IConfiguration configuration)
        {
            _serverRepository = new ServerRepository(dbContext);
            _configuration = configuration;
        }

        public async Task<ResponseApiDto> AddAsync(RequestCommentsAddDto dto, int accountId)
        {
            int affctedRows = 0;
            List<string> tempPaths = new List<string>();
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                // 添加评论
                Comment comment = dto.toEntity(accountId);
                affctedRows += await _serverRepository.commentsEFCore.AddAsync(comment);
                // 添加评论资源
                if (dto.image != null)
                {
                    for (int i = 0; i < dto.image.Count; i++)
                    {
                        string path = Path.Combine(_configuration["ImageBasePath"]!, "Comments", comment.CId.ToString());
                        string fileName = await Upload.UploadImageAsync(dto.image[i], path, true);
                        tempPaths.Add(Path.Combine(path, fileName));
                        CommentResource commentResource = new CommentResource()
                        {
                            CrCommentId = comment.CId,
                            CrExtendName = Path.GetExtension(fileName).ToLowerInvariant(),
                            CrFileName = fileName,
                            CrPath = Path.Combine(Path.Combine(_configuration["CurrentUrl"]!, "Images", "Comments", comment.CId.ToString()), fileName)
                        };
                        affctedRows += await _serverRepository.commentResourcesEFCore.AddAsync(commentResource);
                    }
                }
            }, async () =>
            {
                // 失败清理
                affctedRows = 0;
                for (int i = 0; i < tempPaths.Count; i++)
                {
                    await Upload.DeleteFileAsync(tempPaths[i]);
                }
            });
            return ResponseApiDto.Create(affctedRows);
        }

        public async Task<ResponseApiDto> DeleteAsync(RequestCommentsDeleteDto dto)
        {
            var iq = _serverRepository.commentsEFCore.Query(d => d.CId == dto.commentId);
            int affectedRows = 0;
            string imagePath = Path.Combine(_configuration["ImageBasePath"]!, "Comments", dto.commentId.ToString());
            List<FileInfo> willDeleteImages = new List<FileInfo>();
            await _serverRepository.ExecuteInTransactionAsync(async () =>
            {
                affectedRows += await _serverRepository.commentsEFCore.DeleteAsync(iq);
                List<string> paths = await _serverRepository.commentResourcesEFCore.Query(d => d.CrCommentId == dto.commentId).Select(d => d.CrPath!).ToListAsync();
                for (int i = 0; i < paths.Count; i++)
                {
                    string path = paths[i];
                    willDeleteImages.Add(new FileInfo(path));
                    await Upload.DeleteFileAsync(path);
                }
                if (Directory.Exists(imagePath))
                {
                    Directory.Delete(imagePath);
                }
            }, () =>
             {
                 affectedRows = 0;
                 // 恢复文件夹
                 if (!Directory.Exists(imagePath))
                 {
                     Directory.CreateDirectory(imagePath);
                 }
                 // 恢复图片
                 for (int i = 0; i < willDeleteImages.Count; i++)
                 {
                     var image = willDeleteImages[i];
                     image.CopyTo(Path.Combine(imagePath, image.Name), overwrite: true);
                 }
                 return Task.CompletedTask;
             });
            return ResponseApiDto.Create(affectedRows);
        }

        public async Task<ResponseApiDto> GetPaginationAsync(int page, int limit, int goodId, int? firstId)
        {
            int total = 0;
            var iq = _serverRepository.commentsEFCore.Pagination(d => d.CMainCommentId == null && d.CGoodId == goodId && d.CContent != null && (firstId == null || d.CId != firstId), false, d => d.CCreateTime, out total, page, limit);
            IQueryable<ResponseCommentsDto> resIq= iq.ToResponseCommentsIq();
            List<ResponseCommentsDto> data = await resIq.ToListAsync();
            return ResponseApiDto.Ok("数据已获取", new { data, total });
        }

        private IQueryable<Comment> CommentIq(int gid)
        {
            return _serverRepository.commentsEFCore.Query(d=>d.CGoodId==gid);
        }

        public async Task<ResponseApiDto> GetCommentCountAsync(int gid)
        {
            return ResponseApiDto.Ok("数据已获取", await CommentIq(gid).CountAsync());
        }

        public async Task<ResponseApiDto> GetCommentPenddingPaginationAsync(int page, int limit, int isComment, int aid, int bid)
        {
            int total = 0;
            var iq = _serverRepository.ordersEFCore.Pagination(d => d.OBusinessId == bid && d.OCompleteTime != null && d.OrderDetails.Where(d => ((d.Comment != null) ? 1 : 0) == isComment).Any(), false, d => d.OCompleteTime, out total, page, limit);
            List<ResponseCommentsPenddingDto> data = await iq.ToResponseCommentPenddingIq().ToListAsync();
            return ResponseApiDto.Ok("数据已获取", new { data = data.ToList(), total = total });
        }

        public async Task<ResponseApiDto> GetHotCommentsAsync(int gid, int count)
        {
            var iq = CommentIq(gid).OrderByDescending(d => d.CommentLikes.Count).Take(count);
            List<ResponseCommentsDto> data = await iq.ToResponseCommentsIqNoReplayAndSource().ToListAsync();
            return ResponseApiDto.Ok("数据已获取", data);
        }

        public async Task<ResponseApiDto> GetSingleCommentAsync(int gid, int id)
        {
            var iq = _serverRepository.commentsEFCore.Query(d => d.CGoodId == gid && d.CId == id);
            ResponseCommentsDto? data = await iq.ToResponseCommentsIq().SingleOrDefaultAsync();
            return ResponseApiDto.Ok("数据已获取", data);
        }
    }
}
